package com.topvision.camerasdk.camera.view;

import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.hardware.Camera;
import android.hardware.Camera.Parameters;
import android.os.Build;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.ImageView;

import com.topvision.camerasdk.R;
import com.topvision.camerasdk.camera.CameraActivity;
import com.topvision.camerasdk.camera.TakePhotoCallback;
import com.topvision.camerasdk.camera.util.AutoFocusManager;
import com.topvision.camerasdk.camera.util.CameraUtil;
import com.topvision.camerasdk.utils.CameraSettingsUtil;
import com.topvision.commomsdk.uitl.AndroidUtils;
import com.topvision.commomsdk.uitl.PreferencesUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;


public class CameraView extends SurfaceView implements SurfaceHolder.Callback, Camera.AutoFocusCallback {

    private static final String TAG = "CameraView";
    private SurfaceHolder mHolder;
    private Camera mCamera;
    Context context;
    Parameters parameters;
    ImageView albumIv;
    //缩略图对象
    Bitmap currPhoto;
    private AutoFocusManager mManager;

    int picWidth = 0;
    int picHeight = 0;
    TakePhotoCallback takePhotoCallback;
    CameraActivity cameraActivity;

    public CameraView(Context context, CameraActivity cameraActivity) {
        super(context);
        mHolder = getHolder();
        mHolder.addCallback(this);
        mHolder.setKeepScreenOn(true);
        this.context = context;
        this.cameraActivity = cameraActivity;
    }

    public Camera getCameraInstance() {
        if (mCamera == null) {
            try {
                mCamera = Camera.open();
                if (mCamera != null) {
                    setCameraParameters(mCamera);
                }
            } catch (Exception e) {
                Log.d(TAG, "camera is not available");
                e.printStackTrace();
            }
        }
        return mCamera;
    }

    public void surfaceCreated(SurfaceHolder holder) {
        mCamera = getCameraInstance();
        try {
            if (mCamera != null) {
                mCamera.setPreviewDisplay(holder);
                mCamera.startPreview();
                cameraActivity.setTakingPhoto(false);
            } else {
                AndroidUtils.showTips(context, context.getString(R.string.camera_not_available));
            }
        } catch (IOException e) {
            Log.d(TAG, "Error setting camera preview: " + e.getMessage());
            e.printStackTrace();
        }
    }


    private void setCameraParameters(Camera camera) {
        parameters = camera.getParameters();
        if (PreferencesUtils.getInt(context, "wide", 0) != 0) {
            picWidth = PreferencesUtils.getInt(context, "wide");
            picHeight = PreferencesUtils.getInt(context, "high");
        } else {
            picWidth = CameraActivity.DEFAULT_PICTURE_WIDTH;
            picHeight = CameraActivity.DEFAULT_PICTURE_HEIGHT;
        }

        /* 保证previewSize和pictureSize比率一直，既能baozhen保证全屏预览 */
        /* 相同的分辨率有 /1280,720 / 1920,1080 / 640,480 / 320,240 /  */
        parameters.setPreviewSize(640, 480);
        parameters.setPictureSize(picWidth, picHeight);
        parameters = CameraSettingsUtil.geFromSettings(context, parameters);

        //TODO 经测试。5.1版本 FOCUS_MODE_CONTINUOUS_PICTURE 会导致相机无法打开。猜测是底层BSP没调通
        if (Build.VERSION.SDK_INT >= 21 && !AndroidUtils.isBtDevice()) {
            if (CameraUtil.isSupported(Parameters.FOCUS_MODE_CONTINUOUS_VIDEO, parameters.getSupportedFocusModes())) {
                parameters
                        .setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
            }
        } else {
            if (CameraUtil.isSupported(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE, parameters.getSupportedFocusModes())) {
                parameters
                        .setFocusMode(Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);
            }
        }

        parameters.setPictureFormat(PixelFormat.JPEG); // 设置图片格式
        parameters.setJpegQuality(95); // 设置照片质量
        camera.setParameters(parameters);
        picWidth = parameters.getPictureSize().width;
        picHeight = parameters.getPictureSize().height;
    }


    public void surfaceDestroyed(SurfaceHolder holder) {
        if (mCamera != null) {
            freeCameraResource();
        }
        cameraActivity.setTakingPhoto(true);
    }

    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
        System.out.println("surfaceChanged");
    }


    public void freeCameraResource() {
        if (mCamera != null) {
            mHolder.removeCallback(this);
            mCamera.setPreviewCallback(null);
            //新增的
            mCamera.cancelAutoFocus();
            mCamera.stopPreview();
            mCamera.lock();
            mCamera.release();
            mCamera = null;

        }
    }

    public Parameters getParameters() {
        return parameters;
    }

    public void setParameters(Parameters parameters) {
        this.parameters = parameters;
    }


    boolean flashFlag = false;

    /**
     * 打开闪光灯
     * create at 2017/1/11 10:24
     */
    public boolean openFlashLight() {
        try {
            mCamera.stopPreview();
            parameters.setFlashMode(Parameters.FLASH_MODE_TORCH);
            mCamera.setParameters(parameters);
            mCamera.startPreview();
            flashFlag = true;
        } catch (Exception e) {
            e.printStackTrace();
            flashFlag = false;
        }
        return flashFlag;
    }

    /**
     * 关闭闪光灯
     * create at 2017/1/11 10:35
     */
    public void closeFlashLight() {
        if (flashFlag) {
            try {
                mCamera.stopPreview();
                parameters.setFlashMode(Parameters.FLASH_MODE_OFF);
                mCamera.setParameters(parameters);
                mCamera.startPreview();
                flashFlag = false;
            } catch (Exception e) {
                e.printStackTrace();
                flashFlag = true;
            }

        }

    }

    public boolean isFlashFlag() {
        return flashFlag;
    }

    public void setFlashFlag(boolean flashFlag) {
        this.flashFlag = flashFlag;
    }


    Camera.Area area1;
    Camera.Area area2;
    List<Camera.Area> focusAreas = new ArrayList<Camera.Area>();
    List<Camera.Area> meteringAreas = new ArrayList<Camera.Area>();
    Rect focusRect;
    Rect meteringRect;

    public void focusOnTouch() {
        if (focusRect == null) {
            focusRect = calculateTapArea(250, 200, 1f);
        }
        if (meteringRect == null) {
            meteringRect = calculateTapArea(250, 200, 1.5f);
        }

        Parameters parameters = mCamera.getParameters();
        parameters.setFocusMode(Parameters.FOCUS_MODE_AUTO);

        if (parameters.getMaxNumFocusAreas() > 0) {
            if (area1 == null) {
                area1 = new Camera.Area(focusRect, 1000);
            }
            focusAreas.clear();
            area1.rect = focusRect;
            area1.weight = 1000;
            focusAreas.add(area1);
            parameters.setFocusAreas(focusAreas);
        }

        if (parameters.getMaxNumMeteringAreas() > 0) {
            if (area2 == null) {
                area2 = new Camera.Area(meteringRect, 1000);
            }
            meteringAreas.clear();
            area2.rect = meteringRect;
            area2.weight = 1000;
            meteringAreas.add(area2);
            parameters.setMeteringAreas(meteringAreas);
        }
        mCamera.setParameters(parameters);
        mCamera.cancelAutoFocus();
        mCamera.autoFocus(this);
    }

    private Rect calculateTapArea(float x, float y, float coefficient) {
        float focusAreaSize = 300;
        int areaSize = Float.valueOf(focusAreaSize * coefficient).intValue();

        int centerX = (int) (x / getResolution().width * 2000 - 1000);
        int centerY = (int) (y / getResolution().height * 2000 - 1000);

        int left = clamp(centerX - areaSize / 2, -1000, 1000);
        int right = clamp(left + areaSize, -1000, 1000);
        int top = clamp(centerY - areaSize / 2, -1000, 1000);
        int bottom = clamp(top + areaSize, -1000, 1000);

        return new Rect(left, top, right, bottom);
    }

    private int clamp(int x, int min, int max) {
        if (x > max) {
            return max;
        }
        if (x < min) {
            return min;
        }
        return x;
    }

    public Camera.Size getResolution() {
        Parameters params = mCamera.getParameters();
        Camera.Size s = params.getPreviewSize();
        return s;
    }

    //定点对焦的代码
    public void pointFocus(ImageView albumIv) {
        this.albumIv = albumIv;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
            focusOnTouch();
        }


    }

    @Override
    public void onAutoFocus(boolean success, Camera camera) {
//        if (success) {
        //无论对焦都拍照
        if (takePhotoCallback == null) {
            takePhotoCallback = new TakePhotoCallback(cameraActivity, context, albumIv, picWidth, picHeight);
        }
        mCamera.takePicture(null, null, takePhotoCallback);
        //}
    }

    public int getPicWidth() {
        return picWidth;
    }

    public void setPicWidth(int picWidth) {
        this.picWidth = picWidth;
    }

    public int getPicHeight() {
        return picHeight;
    }

    public void setPicHeight(int picHeight) {
        this.picHeight = picHeight;
    }

    public Camera getmCamera() {
        return mCamera;
    }

}
